'''
@date: 19-Feb-12
@author: Tyson Hamilton
@summary: A simple script that performs a file and 
          directory search; similar to the UNIX 
          application <find>.  Able to handle a files
          and directories, as well as regular expressions.  
          Matches are printed to STDOUT.

@note:  usage: find.py -name NAME [path...]
        -name NAME:  A file or directory name or Perl style
                     regular expression of the file to be found.
        [path...]:   The root directory for starting the search.
'''
import argparse
import os
import sys
import re

class find:
    def find_file(self, path, regexString):
        """ Traverse the file system to find a file.
        
        Searches the file system starting at <path>
        and prints out any directories or files that
        match the regular expression <regexString>.
        
        Args:
            regexString: A string representing a regular expression.
                         This can also be just the file or directory name.
            path: Relative or absolute path to start the search.
        
        Exceptions:
            ValueError: When the directory <path> does not exist
            re.error: When the regular expression <regexString> parsing fails
        """
        # Validate arguments
        if len(path.strip()) == 0:
            raise ValueError("Empty path is not allowed.")
        elif len(regexString.strip()) == 0:
            raise ValueError("Empty search expression not allowed.")
        elif not os.path.isdir(path):
            raise ValueError("Directory does not exist.")
    
        
        # Parse regular expression
        try:
            regex = re.compile(''.join([regexString, '$']))
        except re.error, msg:
            # Raise a nicer looking error
            raise ValueError("Invalid search expression (%s)." % msg)

        
        for root, dirs, files in os.walk(path):
            for curFile in files:
                if re.match(regex, curFile):
                    print "%s%s%s" % (root, os.sep, curFile)
            for curDir in dirs:
                if re.match(regex, curDir):
                    if root.endswith(os.sep):
                        print "%s%s" % (root, curDir)
                    else:
                        print "%s%s%s" % (root, os.sep, curDir)
                         
                
if __name__ == '__main__':
    """Validates required arguments and invokes find_file.
    
    Args:
        path: The directory to begin the search from.
        name: The file name or regular expression to search.
    """
    # Create the parser
    parser = argparse.ArgumentParser(description='A simplified find application.', prog='find.py', add_help=False)
    parser.add_argument('[path...]')
    parser.add_argument('-name', required=True)
    
    # Validate the arguments
    try:
        args = vars(parser.parse_args())
        path = args['[path...]']
    except IOError, msg:
        parser.error(str(msg))
        sys.exit(2)
   
    # Search for the file    
    try:
        find().find_file(path, args['name'])
    except ValueError, msg:
        print "Error: %s" % msg
        sys.exit(3)
    except re.error, msg:
        print "Error: %s" % msg
        sys.exit(4)